home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / asm / adisv1_3.lha / src / decode_ea.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-24  |  10.0 KB  |  352 lines

  1. /*
  2.  * Change history
  3.  * $Log:    decode_ea.c,v $
  4.  * Revision 3.0  93/09/24  17:53:50  Martin_Apel
  5.  * New feature: Added extra 68040 FPU opcodes
  6.  * 
  7.  * Revision 2.5  93/07/18  22:55:43  Martin_Apel
  8.  * *** empty log message ***
  9.  * 
  10.  * Revision 2.4  93/07/11  21:38:04  Martin_Apel
  11.  * Major mod.: Jump table support tested and changed
  12.  * 
  13.  * Revision 2.3  93/07/10  13:01:56  Martin_Apel
  14.  * Major mod.: Added full jump table support. Seems to work quite well
  15.  * 
  16.  * Revision 2.2  93/07/08  22:27:46  Martin_Apel
  17.  * 
  18.  * Minor mod.: Displacements below 4 used with pc indirect indexed are
  19.  *             not entered into the symbol table anymore
  20.  * 
  21.  * Revision 2.1  93/07/08  20:47:04  Martin_Apel
  22.  * Bug fix: Extended precision reals were printed wrong
  23.  * 
  24.  * Revision 2.0  93/07/01  11:53:45  Martin_Apel
  25.  * *** empty log message ***
  26.  * 
  27.  * Revision 1.12  93/07/01  11:38:28  Martin_Apel
  28.  * Minor mod.: PC relative addressing is now marked as such
  29.  * 
  30.  * Revision 1.11  93/06/16  20:26:17  Martin_Apel
  31.  * Minor mod.: Added jump table support. UNTESTED !!!
  32.  * 
  33.  * Revision 1.10  93/06/06  13:45:34  Martin_Apel
  34.  * Minor mod.: Replaced first_pass and read_symbols by pass1, pass2, pass3
  35.  * 
  36.  * Revision 1.9  93/06/03  18:22:12  Martin_Apel
  37.  * Minor mod.: Addressing relative to hunk end changed
  38.  * 
  39.  */
  40.  
  41. #include <exec/types.h>
  42. #include <string.h>
  43. #include <stdlib.h>
  44. #include "defs.h"
  45.  
  46. static char rcsid [] = "$Id: decode_ea.c,v 3.0 93/09/24 17:53:50 Martin_Apel Exp $";
  47.  
  48. int decode_ea (short mode, short reg, char *where_to, 
  49.                short access, short first_ext)
  50.  
  51. /* returns the number of extension words used for ea */
  52. {
  53. ULONG ref;
  54. register UWORD first_word;
  55. /* Used for jump table disassembly */
  56. static ULONG last_code_reference = UNSET;
  57.  
  58.  
  59. if (pass2 && mode <= 4)
  60.   return (0);
  61.  
  62. first_word = *(code + first_ext);
  63. switch (mode)
  64.   {
  65.   /********************** data register direct ************************/
  66.  
  67.   case 0:
  68.     strcpy (where_to, reg_names [reg]);
  69.     return (0);
  70.  
  71.   /********************* address register direct **********************/
  72.  
  73.   case 1:
  74.     if (access & ACC_BYTE)
  75.       {
  76.       detected_illegal = TRUE;
  77.       return (0);
  78.       }
  79.     strcpy (where_to, reg_names [reg + 8]);
  80.     return (0);
  81.  
  82.   /********************** address register indirect *******************/
  83.  
  84.   case 2:
  85.     indirect (where_to, (short)(reg + 8));
  86.     return (0);
  87.  
  88.   /************ address register indirect post-increment **************/
  89.  
  90.   case 3:
  91.     post_inc (where_to, (short)(reg + 8));
  92.     return (0);
  93.  
  94.   /************* address register indirect pre-decrement **************/
  95.  
  96.   case 4:
  97.     pre_dec (where_to, (short)(reg + 8));
  98.     return (0);
  99.  
  100.   /************* address register indirect with displacement **********/
  101.  
  102.   case 5:
  103.     if (try_small && reg == 4)
  104.       {
  105.       ref = (short)first_word + a4_offset;
  106.       if (pass3)
  107.         gen_label (where_to, ref, TRUE);
  108.       else
  109.         enter_ref (ref, 0L, access);
  110.       }
  111.     else if (pass3)
  112.       disp_an (where_to, (short)(reg + 8), (short)first_word);
  113.     return (1);
  114.  
  115.   /****************** address register indirect indexed ***************/
  116.  
  117.   case 6:
  118.     if (first_word & 0x100)
  119.       {
  120.       if (mc68020 && ext_68020_modes)
  121.         return (full_extension (where_to, code + first_ext, mode, reg));
  122.       else
  123.         {
  124.         detected_illegal = TRUE;
  125.         return (0);
  126.         }
  127.       }
  128.     else
  129.       {
  130.       short size = (first_word >> 9) & 0x3;
  131.  
  132.       if (!mc68020 && size != 0)        /* Only size of 1 allowed for 68000 */
  133.         {
  134.         detected_illegal = TRUE;
  135.         return (0);
  136.         }
  137.       if (pass3)
  138.         {
  139.         /* To get the sign right */
  140.         disp_an_indexed (where_to, (short)(reg + 8),
  141.                          (char)first_word,
  142.                          (short)(first_word >> 12),
  143.                          (short)(1 << size),
  144.                          (first_word & 0x0800) ? ACC_LONG : ACC_WORD);
  145.         }
  146.       return (1);
  147.       }
  148.  
  149.   /************************* Mode 7 with submodes *********************/
  150.  
  151.   case 7:
  152.     switch (reg)
  153.       {
  154.       /*********************** absolute short *********************/
  155.  
  156.       case 0:
  157.         if (pass3)
  158.           format_d (where_to, first_word, FALSE);
  159.         return (1);
  160.  
  161.       /*********************** absolute long **********************/
  162.  
  163.       case 1:
  164.         ref = (first_word << 16) + *(code + first_ext + 1);
  165.         if (IS_RELOCATED (current_address + first_ext * 2))
  166.           {
  167.           if (pass2)
  168.             {
  169.             enter_ref (ref, NULL, access);
  170.             if (ref >= first_address && ref < last_address && EVEN (ref))
  171.               last_code_reference = ref;
  172.             }
  173.           else
  174.             /* This reference is relocated and thus needs a label */
  175.             gen_label (where_to, ref, TRUE);
  176.           }
  177.         else if (pass3)
  178.           format_ld (where_to, ref, FALSE);
  179.         return (2);
  180.  
  181.       /************************** d16(PC) *************************/
  182.  
  183.       case 2:
  184. /* It's possible, that a program accesses its hunk structure PC relative,
  185.    thus it generates a reference to a location outside valid code addresses */
  186.         ref = current_address + 2 + (short)first_word;
  187.         if (pass3)
  188.           {
  189.           if ((long)ref < (long)first_address)
  190.             {
  191.             gen_label (where_to, first_address, TRUE);
  192.             strcat (where_to, "-");
  193.             format_ld (where_to + strlen (where_to), 
  194.                        *(hunk_start + current_hunk) - ref, TRUE);
  195.             }
  196.           else if (ref >= last_address)
  197.             {
  198.             gen_label (where_to, last_address, TRUE);
  199.             strcat (where_to, "+");
  200.             format_ld (where_to + strlen (where_to), 
  201.                        ref - *(hunk_end + current_hunk), TRUE);
  202.             }
  203.           else
  204.             gen_label (where_to, ref, TRUE);
  205.           strcat (where_to, "(");
  206.           strcat (where_to, reg_names [PC]);
  207.           strcat (where_to, ")");
  208.           }
  209.         else if (ref >= first_address && ref < last_address)
  210.           {
  211.           enter_ref (ref, NULL, access);
  212.           if (EVEN (ref))
  213.             last_code_reference = ref;
  214.           }
  215.             
  216.         return (1);
  217.  
  218.       /***************** PC memory indirect with index ************/
  219.  
  220.       case 3:
  221.         if (first_word & 0x0100)
  222.           {
  223.           /* long extension word */
  224.           if (mc68020 && ext_68020_modes)
  225.             return (full_extension (where_to, code + first_ext, mode, reg));
  226.           else
  227.             {
  228.             detected_illegal = TRUE;
  229.             return (0);
  230.             }
  231.           }
  232.         else
  233.           {
  234.           /* short extension word */
  235.           short size = (first_word >> 9) & 0x3;
  236.  
  237.           if (!mc68020 && size != 0)        /* Only size of 1 allowed for 68000 */
  238.             {
  239.             detected_illegal = TRUE;
  240.             return (0);
  241.             }
  242.          if (pass3)
  243.            disp_an_indexed (where_to, PC, (char)first_word,
  244.                             (short)(first_word >> 12),
  245.                             (short)(1 << size),
  246.                             (first_word & 0x0800) ? ACC_LONG : ACC_WORD);
  247.          else
  248.            {
  249.            ref = current_address + (char)first_word + 2;
  250.            /* Check for JMP (PC,Dx) opcode */
  251.            if (*code == 0x4efb)
  252.              {
  253.              enter_jmptab (last_code_reference, (ULONG)((char)first_word));
  254.              enter_ref (current_address, NULL, ACC_CODE);
  255.              }
  256.            else
  257.              {
  258.              if (ref >= first_address && ref < last_address)
  259.                {
  260.                enter_ref (ref, NULL, access);
  261.                last_code_reference = ref;
  262.                }
  263.              }
  264.            }
  265.           return (1);
  266.           }
  267.  
  268.       /************************ immediate *************************/
  269.  
  270.       case 4:
  271.         if (access & ACC_BYTE)
  272.           {
  273.           if (pass3)
  274.             {
  275.             *where_to = '#';
  276.             format_d (where_to + 1, (short)(first_word & 0xff), TRUE);
  277.             }
  278.           return (1);
  279.           }
  280.         else if (access & ACC_WORD)
  281.           {
  282.           if (pass3)
  283.             {
  284.             *where_to = '#';
  285.             format_d (where_to + 1, (short)first_word, TRUE);
  286.             }
  287.           return (1);
  288.           }
  289.         else if (access & ACC_LONG)
  290.           {
  291.           ref = (first_word << 16) + *(code + first_ext + 1);
  292.           if (IS_RELOCATED (current_address + first_ext * 2))
  293.             {
  294.             if (pass2)
  295.               {
  296.               enter_ref (ref, NULL, access);
  297.               if (ref >= first_address && ref < last_address && EVEN (ref))
  298.                 last_code_reference = ref;
  299.               }
  300.             else
  301.               {
  302.               /* This reference is relocated and thus needs a label */
  303.               *where_to++ = '#';
  304.               *where_to++ = '(';
  305.               gen_label (where_to, ref, TRUE);
  306.               strcat (where_to, ")");
  307.               }
  308.             }
  309.           else if (pass3)
  310.             {
  311.             *where_to = '#';
  312.             format_ld (where_to + 1, ref, TRUE);
  313.             }
  314.           return (2);
  315.           }
  316.         else if (access & ACC_DOUBLE)
  317.           {
  318.           if (pass3)
  319.             {
  320.             sprintf (where_to, "#$%lx%08lx", *(ULONG*)(code + first_ext),
  321.                      *(ULONG*)(code + first_ext + 2));
  322.             }
  323.           return (4);
  324.           }
  325.         else if (access & ACC_EXTEND)
  326.           {
  327.           if (pass3)
  328.             {
  329.             sprintf (where_to, "#$%lx%08lx%08lx", *(ULONG*)(code + first_ext),
  330.                      *(ULONG*)(code + first_ext + 2), 
  331.                      *(ULONG*)(code + first_ext + 4));
  332.             }
  333.           return (6);
  334.           }
  335.         else
  336.           {
  337.           fprintf (stderr, "INTERNAL ERROR: decode_ea: immediate addressing with unknown size\n");
  338.           fprintf (stderr, "    Current address is: %lx\n", current_address);
  339.           }
  340.         break;
  341.       default:
  342.         /* Should not occur, as it should be caught by the submode test
  343.            in disasm.c */
  344.         detected_illegal = TRUE;
  345.         fprintf (stderr, "INTERNAL ERROR: decode_ea: illegal submode\n");
  346.         fprintf (stderr, "    Current address is: %lx\n", current_address);
  347.       }
  348.     break;    
  349.   }
  350. return (0);
  351. }
  352.